/*************************************************
* Title：TinyToolKit
* Author：Opportunity 
* Describe：数据节点
* CreateTime：2021-03-01 13:53:54
* Version：1.0
* Modify Recorder：
*************************************************/

using System.Collections.Generic;
using System.Diagnostics;

namespace TinyToolKit.DataTree
{
    public class DataNode : IReference
    {
        private string _name;
        private TinyData _data;
        private DataNode _parent;
        private List<DataNode> _children;
        
        public string Name => _name;
        public string FullName => _parent == null ? _name : $"{_parent.FullName}.{_name}";
        public DataNode Parent => _parent;
        public int ChildCount => _children?.Count ?? 0;

        public DataNode()
        {
            _name = "";
            _data = null;
            _parent = null;
            _children = null;
        }
        
        public DataNode(string name)
        {
            _name = name;
            _data = null;
            _parent = null;
            _children = null;
        }

        /// <summary>
        /// 设置数据
        /// </summary>
        /// <param name="data">数据</param>
        /// <typeparam name="T">数据类型</typeparam>
        public void SetData<T>(T data) where T : TinyData
        {
            _data = data;
        }
        
        /// <summary>
        /// 获取数据
        /// </summary>
        /// <typeparam name="T">数据类型</typeparam>
        /// <returns>返回数据</returns>
        public T GetData<T>() where T : TinyData
        {
            return _data as T;
        }
        
        /// <summary>
        /// 清除数据
        /// </summary>
        public void ClearData() 
        {
            _data = null;
        }

        /// <summary>
        /// 根据名字判断是否存在子结点
        /// </summary>
        /// <param name="name">结点名字</param>
        /// <returns>存在该结点返回true,否则返回false</returns>
        public bool HasChildNode(string name)
        {
            if (name.IsNullOrEmpty()) return false; 
            if (_children == null) return false;

            for (int i = 0; i < _children.Count; i++)
            {
                if (_children[i]._name == name)
                    return true;
            }

            return false;
        }

        /// <summary>
        /// 添加子节点
        /// </summary>
        /// <param name="name">结点名</param>
        /// <param name="data">结点数据</param>
        /// <returns>创建成功则返回结点</returns>
        public DataNode AddChildNode(string name,TinyData data)
        {
            if (name.IsNullOrEmpty()) return null;
            if (HasChildNode(name)) return GetChildNode(name);

            DataNode node = TReferencePool.Acquire<DataNode>();
            node._name = name;
            node._parent = this;
            node._data = data;
            if(_children == null) _children = new List<DataNode>();
            _children.Add(node);
            
            return node;
        }

        /// <summary>
        /// 根据名字获取子结点
        /// </summary>
        /// <param name="name">结点的名字</param>
        /// <returns>如果对应的结点存在则返回，否则返回空</returns>
        public DataNode GetChildNode(string name)
        {
            if (name.IsNullOrEmpty()) return null;
            if (_children == null) return null;
            
            for (int i = 0; i < _children.Count; i++)
            {
                if (_children[i]._name == name)
                    return _children[i];
            }
            
            return null;
        }
        
        /// <summary>
        /// 获取所有的子结点
        /// </summary>
        /// <returns>如果子节点存在，则全部返回，否则返回空</returns>
        public DataNode[] GetAllChildNodes()
        {
            return _children?.ToArray();
        }

        /// <summary>
        /// 移除子结点
        /// </summary>
        /// <param name="name">结点名字</param>
        public void RemoveChildNode(string name)
        {
            DataNode node = GetChildNode(name);
            if (node == null) return;
            _children.Remove(node);
            TReferencePool.Release(node);
        }
        
        /// <summary>
        /// 移除所有子节点
        /// </summary>
        public void RemoveAllChildNodes()
        {
            if (_children == null) return;
            
            for (int i = 0; i < _children.Count; i++)
            {
                _children[i].RemoveAllChildNodes();
                TReferencePool.Release(_children[i]);
            }
            _children.Clear();
        }

        /// <summary>
        /// 清空该结点数据，且移除所有子节点
        /// </summary>
        public void Clear()
        {
            _name = null;
            _data = null;
            _parent = null;
            
            RemoveAllChildNodes();
        }

        public override string ToString()
        {
            return _data == null ? "" : $"{FullName}：{ToDataString()}";
        }

        public string ToDataString()
        {
            return _data == null ? "" : $"[{_data.GetType().Name}] {_data}";
        }
    }
}

